package org.jacp.demo.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * 
 * @author Chet
 */
public class IntermediateImages extends JComponent {

    /**
     * 
     */
    private static final long serialVersionUID = -1958735206517238453L;
    private static final int SCALE_X = 20;
    private static final int SMILEY_X = 200;
    private static final int DIRECT_Y = 10;
    private static final int INTERMEDIATE_Y = 260;
    private static final int SMILEY_SIZE = 100;
    private static BufferedImage picture = null;
    private BufferedImage scaledImage = null;
    private BufferedImage smileyImage = null;
    private static final double SCALE_FACTOR = .1;
    private int scaleW, scaleH;

    /** Creates a new instance of IntermediateImages */
    public IntermediateImages() {
	try {
	    final File url = new File("/home/amo/Bilder/IMG_4935_1.jpg");
	    picture = ImageIO.read(url);
	    scaleW = (int) (SCALE_FACTOR * picture.getWidth());
	    scaleH = (int) (SCALE_FACTOR * picture.getHeight());
	} catch (final Exception e) {
	    System.out.println("Problem reading image file: " + e);
	    System.exit(0);
	}
    }

    /**
     * Draws both the direct and intermediate-image versions of a scaled-image,
     * timing both variations.
     */
    private void drawScaled(final Graphics g) {
	long startTime, endTime, totalTime;

	// Scaled image
	((Graphics2D) g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,
		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	startTime = System.nanoTime();
	for (int i = 0; i < 100; ++i) {
	    g.drawImage(picture, SCALE_X, DIRECT_Y, scaleW, scaleH, null);
	}
	endTime = System.nanoTime();
	totalTime = (endTime - startTime) / 1000000;
	g.setColor(Color.BLACK);
	g.drawString("Direct: " + ((float) totalTime / 100) + " ms", SCALE_X,
		DIRECT_Y + scaleH + 20);
	System.out.println("scaled: " + totalTime);

	// Intermediate Scaled
	// First, create the intermediate image
	if (scaledImage == null || scaledImage.getWidth() != scaleW
		|| scaledImage.getHeight() != scaleH) {
	    final GraphicsConfiguration gc = getGraphicsConfiguration();
	    scaledImage = gc.createCompatibleImage(scaleW, scaleH);
	    final Graphics gImg = scaledImage.getGraphics();
	    ((Graphics2D) gImg).setRenderingHint(
		    RenderingHints.KEY_INTERPOLATION,
		    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	    gImg.drawImage(picture, 0, 0, scaleW, scaleH, null);
	}
	// Now, copy the intermediate image into place
	startTime = System.nanoTime();
	for (int i = 0; i < 100; ++i) {
	    g.drawImage(scaledImage, SCALE_X, INTERMEDIATE_Y, null);
	}
	endTime = System.nanoTime();
	totalTime = (endTime - startTime) / 1000000;
	g.drawString("Intermediate: " + ((float) totalTime / 100) + " ms",
		SCALE_X, INTERMEDIATE_Y + scaleH + 20);
	System.out.println("Intermediate scaled: " + totalTime);
    }

    private void renderSmiley(final Graphics g, final int x, final int y) {
	final Graphics2D g2d = (Graphics2D) g.create();

	// Yellow face
	g2d.setColor(Color.yellow);
	g2d.fillOval(x, y, SMILEY_SIZE, SMILEY_SIZE);

	// Black eyes
	g2d.setColor(Color.black);
	g2d.fillOval(x + 30, y + 30, 8, 8);
	g2d.fillOval(x + 62, y + 30, 8, 8);

	// Black outline
	g2d.drawOval(x, y, SMILEY_SIZE, SMILEY_SIZE);

	// Black smile
	g2d.setStroke(new BasicStroke(3.0f));
	g2d.drawArc(x + 20, y + 20, 60, 60, 190, 160);

	g2d.dispose();
    }

    /**
     * Draws both the direct and intermediate-image versions of a smiley face,
     * timing both variations.
     */
    private void drawSmiley(final Graphics g) {
	long startTime, endTime, totalTime;

	// Draw smiley directly
	startTime = System.nanoTime();
	for (int i = 0; i < 100; ++i) {
	    renderSmiley(g, SMILEY_X, DIRECT_Y);
	}
	endTime = System.nanoTime();
	totalTime = (endTime - startTime) / 1000000;
	g.setColor(Color.BLACK);
	g.drawString("Direct: " + ((float) totalTime / 100) + " ms", SMILEY_X,
		DIRECT_Y + SMILEY_SIZE + 20);
	System.out.println("Direct: " + totalTime);

	// Intermediate Smiley
	// First, create the intermediate image if necessary
	if (smileyImage == null) {
	    final GraphicsConfiguration gc = getGraphicsConfiguration();
	    smileyImage = gc.createCompatibleImage(SMILEY_SIZE + 1,
		    SMILEY_SIZE + 1, Transparency.BITMASK);
	    final Graphics2D gImg = (Graphics2D) smileyImage.getGraphics();
	    renderSmiley(gImg, 0, 0);
	    gImg.dispose();
	}
	// Now, copy the intermediate image
	startTime = System.nanoTime();
	for (int i = 0; i < 100; ++i) {
	    g.drawImage(smileyImage, SMILEY_X, INTERMEDIATE_Y, null);
	}
	endTime = System.nanoTime();
	totalTime = (endTime - startTime) / 1000000;
	g.drawString("Intermediate: " + ((float) totalTime / 100) + " ms",
		SMILEY_X, INTERMEDIATE_Y + SMILEY_SIZE + 20);
	System.out.println("intermediate smiley: " + totalTime);
    }

    @Override
    protected void paintComponent(final Graphics g) {
	g.setColor(Color.WHITE);
	g.fillRect(0, 0, getWidth(), getHeight());
	drawScaled(g);
	drawSmiley(g);
    }

    private static void createAndShowGUI() {
	final JFrame f = new JFrame("IntermediateImages");
	f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	f.setSize(360, 540);
	f.add(new IntermediateImages());
	f.setVisible(true);
    }

    public static void main(final String args[]) {
	final Runnable doCreateAndShowGUI = new Runnable() {
	    @Override
	    public void run() {
		createAndShowGUI();
	    }
	};
	SwingUtilities.invokeLater(doCreateAndShowGUI);
    }
}